import React, { Component, cloneElement } from 'react';
import PropTypes from 'prop-types';

import styles from './style.scss';
import { noop } from '@utils';

export default class Menu extends Component {
    static propTypes = {
        defaultActiveKeys: PropTypes.array,
        defaultExpandedKeys: PropTypes.array,
        activeKeys: PropTypes.array,
        expandedKeys: PropTypes.array,
        onClick: PropTypes.func,
        onSelect: PropTypes.func,
        onDeselect: PropTypes.func,
        onExpand: PropTypes.func,
        onDestory: PropTypes.func,
        children: PropTypes.any,
        className: PropTypes.string,
        style: PropTypes.object,
    };

    static defaultProps = {
        defaultActiveKeys: [],
        defaultExpandedKeys: [],
        onClick: noop,
        onSelect: noop,
        onDeselect: noop,
        onExpand: noop,
        onDestory: noop,
        className: '',
        style: {}
    };

    constructor(props) {
        super(props);
        
        this.state = {
            expandedKeys: props.expandedKeys && props.expandedKeys.map(item => String(item)) || props.defaultExpandedKeys,
            activeKeys: props.activeKeys &&  props.activeKeys.map(item => String(item)) || props.defaultActiveKeys,
        };
    }

    componentWillReceiveProps(nextProps) {
        if ('expandedKeys' in nextProps) {
            this.setState({
                expandedKeys: nextProps.expandedKeys && nextProps.expandedKeys.map(item => String(item)) || []
            });
        }
        if ('activeKeys' in nextProps) {
            this.setState({
                activeKeys: nextProps.activeKeys && nextProps.activeKeys.map(item => String(item)) || []
            });
        }
    }

    onSelect = data => {
        const props = this.props;
        const menuKey = data.menuKey;
        let activeKeys = this.state.activeKeys ? [...this.state.activeKeys] : [];
        if (activeKeys.indexOf(menuKey) === -1) {
            activeKeys = [];
            let item = data.item;
            while (item && item.props.parentMenu) {
                activeKeys.push(item.props.menuKey);
                item = item.props.parentMenu;
            }
            if (!('activeKeys' in props)) {
                this.setState({
                    activeKeys
                });
            }
            props.onSelect({
                ...data,
                activeKeys
            });
        }
    };

    onExpand = ({ isExpanded, menuKey, item }) => {
        const props = this.props;
        let expandedKeys = this.state.expandedKeys ? [...this.state.expandedKeys] : [];
        let needUpdateState = false;
        const idx = expandedKeys.indexOf(menuKey);
        if (isExpanded && idx === -1) {
            needUpdateState = true;
            expandedKeys.push(menuKey);
        } else if (!isExpanded && idx !== -1) {
            needUpdateState = true;
            expandedKeys.splice(idx, 1);
        }
        if (needUpdateState) {
            if (!('expandedKeys' in props)) {
                this.setState({
                    expandedKeys
                });
            }
            props.onExpand(expandedKeys);
        }
    };

    onClick = evt => {
        this.props.onClick(evt);
    };


    render() {
        return (
            <ul className={styles.menu}>
                {
                    this.props.children && this.renderChildren(this.props.children)
                }
            </ul>
        );
    }

    renderChildren(children) {
        const props = this.props;
        let { activeKeys, expandedKeys } = this.state;
        activeKeys = activeKeys || [];
        expandedKeys = expandedKeys || [];
        let childProps = {
            onClick: this.onClick,
            onSelect: this.onSelect,
            parentMenu: this,
            rootMenu: this,
            activeKeys: activeKeys,
            onDeselect: props.onDeselect,
            onDestory: props.onDestory,
        };
        return (
            React.Children.map(children, child => {
                const menuKey = String(child.props.menuKey);
                if (child.type.isMenuItem) {
                    return cloneElement(child, {
                        ...childProps,
                        isActive: activeKeys.indexOf(menuKey) !== -1,
                    });
                } else if (child.type.isSubMenu) {
                    return cloneElement(child, {
                        ...childProps,
                        isActive: activeKeys.indexOf(menuKey) !== -1,
                        isExpanded: expandedKeys.indexOf(menuKey) !== -1 ? true : false,
                        onExpand: this.onExpand,
                        expandedKeys: expandedKeys,
                    });
                }
                return child;
            })
        );
    }
}

